#ifndef __TIMING_HPP__
#define __TIMING_HPP__

#include <iostream>
#include <sstream>
#include <string>
#include <cassert>

#include "tbb/tick_count.h"

#include "Threading.hpp"


class MasterTimer {
  std::string name;
  double *global_timer;
public:
  MasterTimer() : global_timer(nullptr) {}
  void setTimer(std::string s, double *g) {name = s; global_timer = g; }
  ~MasterTimer() {
#ifdef MEASURE_OVERHEADS
    std::stringstream ss;
    ss << "All Threads Overhead " << name << " is: " << *global_timer << " seconds\n";
    Threading::dump(std::cerr, ss.str());
#endif
  }
};

class Timer {
  double *global_timer;
  tbb::tick_count tick;

  static inline std::mutex &timer_mutex() {
    static std::mutex the_mutex;
    return the_mutex;
  }
public:
  Timer(double &g) : global_timer(&g), tick(tbb::tick_count::now()) {}
  ~Timer() {
#ifdef MEASURE_OVERHEADS
    double d = (tbb::tick_count::now() - tick).seconds();
    // Could put an atomic here.
    timer_mutex().lock();
    *(global_timer) += d;
    timer_mutex().unlock();
    tick = tbb::tick_count::now();
#endif
  }
};
#endif // __TIMING_HPP__
